﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Reviewer.Entities.Services;
using Reviewer.Data;
using System.Web;
using Reviewer.Entities;
using System.Web.Caching;
using System.Collections.ObjectModel;

namespace Reviewer.Business.Services
{
    internal class GameService : BaseService, IGameService, IGameAdminService
    {
        internal GameService() : base() { }

        /// <summary>
        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
        /// </summary>
        public void Dispose()
        {
            GC.SuppressFinalize(this);
        }

        /// <summary>
        /// Gets all.
        /// </summary>
        /// <returns></returns>
        public Game[] GetAll()
        {
            return new GameRepository().SelectAll().ToArray();
        }


        public Game GetBy(Int32 id)
        {
            return new GameRepository().SelectBy(id);
        }

        public Game[] GetBy(Guid gameId)
        {
            return new GameRepository().SelectByAlternateKey(gameId).ToArray();
        }

        public GameTopImage GetAssociatedTopImage(Guid gameId)
        {
            return new GameTopImageRepository().SelectBy(gameId);
        }

        public GameScreenshot[] GetAssociatedScreenshots(Guid gameId)
        {
            return new GameScreenshotRepository().SelectByAlternateKey(gameId).ToArray();
        }

        public GameVideo GetAssociatedVideo(Guid gameId)
        {
            ICollection<GameVideo> videos = new GameVideoRepository().SelectByAlternateKey(gameId);
            if (videos.Count > 0)
            {
                return videos.ElementAt(0);
            }

            return null;
        }

        public GameVideo[] GetLatestVideos(int topCount)
        {
            return new GameVideoRepository().SelectLatest(topCount).ToArray();
        }

        public Game[] FindGamesWithMissingScreenshots()
        {
            return new GameRepository().SelectWithMissingScreenshots().ToArray();
        }

        public Game[] FindGamesByTitle(string title)
        {
            return new GameRepository().Find(title).ToArray();
        }

        public Game[] GetAllByNewsRelation(Guid newsId)
        {
            return new GameRepository().SelectByNewsRelation(newsId).ToArray();
        }

        public ICollection<Game> Search(string title, Int32? format, int maxResult)
        {
            return new GameRepository().Search(title, format, maxResult);
        }

        public ICollection<Game> SearchFutureReleases(Int32? releaseMonth, Int32? format, int maxResults)
        {
            return new GameRepository().SearchFutureReleases(releaseMonth, format, maxResults);
        }

        public Game[] FindGamesByReleaseDate(int month, int year)
        {
            return new GameRepository().SelectByReleaseDate(month, year).ToArray();
        }

        public void Delete(Guid gameId)
        {
            Game[] games = this.GetBy(gameId);
            using (IReviewAdminService reviewAdmin = ServiceFactory.ReviewAdminService)
            {
                foreach (Game game in games)
                {
                    reviewAdmin.DeleteByGameId(game.Id);
                }
            }
            new GameTopImageRepository().Delete(gameId);
            new GameVideoRepository().DeleteByAlternateKey(gameId);
            new GameScreenshotRepository().DeleteByAlternateKey(gameId);
            new GameRepository().DeleteByAlternateKey(gameId);
        }

        public Game[] Save(Game game)
        {
            GameRepository repository = new GameRepository();
            if (game.Id <= 0)
            {
                game.GameId = Guid.NewGuid();
                repository.Create(game);
            }
            else
            {
                repository.Update(game);
            }

            return repository.SelectByAlternateKey(game.GameId).ToArray();
        }

        public Game[] Save(Game[] games)
        {
            Guid gameId = Guid.NewGuid();
            foreach (Game g in games)
            {
                if (!g.GameId.Equals(Guid.Empty))
                {
                    gameId = g.GameId;
                    break;
                }
            }

            if (gameId.Equals(Guid.Empty))
            {
                gameId = Guid.NewGuid();
            }

            GameRepository repository = new GameRepository();
            List<Game> savedItems = new List<Game>();
            foreach (Game g in games)
            {
                if (g.GameId.Equals(Guid.Empty))
                    g.GameId = gameId;
                if (g.Id <= 0)
                {
                    savedItems.Add(repository.Create(g));
                }
                else
                {
                    savedItems.Add(repository.Update(g));
                }
            }

            Collection<Game> allGames = repository.SelectByAlternateKey(gameId);
            if (allGames.Count() != savedItems.Count)
            {
                for (int i = 0; i < allGames.Count; i++)
                {
                    bool found = false;
                    foreach (Game sg in savedItems)
                    {
                        if (allGames[i].Id.Equals(sg.Id))
                        {
                            found = true;
                            break;
                        }
                    }

                    if (!found)
                    {
                        repository.Delete(allGames[i].Id);
                        allGames.RemoveAt(i);
                    }
                }
            }

            return savedItems.ToArray();
        }

        public void SetAssociatedTopImage(GameTopImage image)
        {
            if (new GameTopImageRepository().Update(image) == null)
            {
                new GameTopImageRepository().Create(image);
            }
        }

        public void AddAssociatedScreenshot(GameScreenshot screenshot)
        {
            GameScreenshotRepository repository = new GameScreenshotRepository();
            repository.Create(screenshot);
        }

        public void AddAssociatedScreenshots(GameScreenshot[] screenshots)
        {
            GameScreenshotRepository reprository = new GameScreenshotRepository();
            foreach (GameScreenshot shot in screenshots)
            {
                reprository.Create(shot);
            }
        }

        public void DeleteAssociatedScreenshotBy(int id)
        {
            GameScreenshotRepository repository = new GameScreenshotRepository();
            repository.Delete(id);
        }

        public void DeleteAssociatedScreenshotsBy(string fileName)
        {
            GameScreenshotRepository repository = new GameScreenshotRepository();
            repository.DeleteByFileName(fileName);

        }

        public void SetAssociatedVideo(GameVideo video)
        {
            GameVideoRepository repository = new GameVideoRepository();
            if (repository.Update(video) == null)
            {
                repository.Create(video);
            }
        }

        public void ClearAssociatedVideo(Guid gameId)
        {
            GameVideoRepository repository = new GameVideoRepository();
            repository.DeleteByAlternateKey(gameId);
        }


        public ICollection<PEGIRating> GetRatings(Guid gameId)
        {
            ReviewerDBContext context = new ReviewerDBContext();
            return context.PEGIRating.Where(t => t.GameId.Equals(gameId)).ToList();
        }

        public void SetRatings(Guid gameId, ICollection<PEGIRating> ratings)
        {
            ReviewerDBContext context = new ReviewerDBContext();

            List<PEGIRating> originalRatings = context.PEGIRating.Where(t => t.GameId.Equals(gameId)).ToList();

            foreach (PEGIRating rating in ratings)
            {
                if (rating.GameId != gameId)
                    rating.GameId = gameId;

                originalRatings.RemoveAll(t => t.GameId == gameId && t.Format == rating.Format);

                context.PEGIRating.InsertOrUpdate(rating);
            }

            foreach (PEGIRating leftover in originalRatings)
            {
                context.PEGIRating.Delete(leftover);
            }
        }




        public GameFactsheet GetFactsheet(Guid gameId)
        {
            ReviewerDBContext context = new ReviewerDBContext();
            return context.GameFactsheet.FirstOrDefault(t => t.GameId.Equals(gameId));
        }

        public GameFactsheet SetFactsheet(GameFactsheet factsheet)
        {
            ReviewerDBContext context = new ReviewerDBContext();
            context.GameFactsheet.InsertOrUpdate(factsheet);
            return GetFactsheet(factsheet.GameId);
        }


    }
}
